/*    
    OpenMheg - A free MHEG-5 library
    Copyright (C) 2008 Dharmesh Malam

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

using System;
using System.Collections.Generic;
using System.Text;
using Core.Model.Events;
using Core.Model.Data.Variables;
using Core.Model.Data.Generics;
using Engine;

namespace Core.Model.Ingredients
{
    public abstract class Program : Ingredient
    {

        #region Exchanged Attributes
        private String name;

        public String Name
        {
            get { return name; }
            set { name = value; }
        }
        private bool initiallyAvailable = true;

        public bool InitiallyAvailable
        {
            get { return initiallyAvailable; }
            set { initiallyAvailable = value; }
        }
        #endregion

        #region Implementation Specific
                
        private List<Generic> parameters;

        internal List<Generic> Parameters
        {
            get { return parameters; }
            set { parameters = value; }
        }
        private bool synchronous = false;

        internal bool Synchronous
        {
            get { return synchronous; }
            set { synchronous = value; }
        }
        private bool executionSucceeded = false;

        internal bool ExecutionSucceeded
        {
            get { return executionSucceeded; }
            set { executionSucceeded = value; }
        }

        public Program ():base()
        {            
            InitiallyActive = false;
        }

        public override void InittInternalAttributes ()
        {
            base.InittInternalAttributes();
         
        }

        public abstract bool Execute (Generic [] parameters);
        #endregion

        #region Event link collections

        //internal List<Link> asynchStopped = new List<Link>();

        //#endregion

        //#region Event Processing
        //public override void handle ( Events.Event evnt )
        //{
        //    switch ( evnt.Type )
        //    {
        //        case enumEvents.AsynchStopped:
        //            foreach ( Link l in asynchStopped )
        //                l.fire();
        //            break;
        //        default:
        //            base.handle( evnt );
        //            break;
        //    }
        //}

        //public override void addLink ( Link link )
        //{
        //    if ( link.LinkCondition.EventSource.Equals( ObjectIdentifier ) )
        //    {
        //        switch ( link.LinkCondition.EventType )
        //        {
        //            case enumEvents.AsynchStopped:
        //                asynchStopped.Add( link );
        //                break;

        //            default:
        //                base.addLink( link );
        //                break;
        //        }
        //    }
        //}
        #endregion

        #region Internal Behaviours

        public override void Activate ()
        {
            if ( !RunningStatus )
            {
                base.Activate();
                                                
                RunningStatus = true;
                Engine.MHEGEngine.Instance.Handle( new IsRunning( this ) );

            }
        }

        public override void Deactivate ()
        {
            if ( RunningStatus )
            {
                //end program!
                base.Deactivate();
            }
        }

        #endregion

        #region Actions
        public sealed override void SetData ( GenericContentRef newContent )
        {
            log.Warn( "SetData: Should not be applied to "+this+". Ignoring" );
        }

        public sealed override void SetData ( GenericOctetString newContent )
        {
            log.Warn( "SetData: Should not be applied to "+this+". Ignoring" );
        }

        public virtual void Call ( BooleanVariable callSucceeded, List<Generic> parameters )
        {
            if ( !AvailabilityStatus )
                Prepare();

            if ( !RunningStatus )
            {   
                Synchronous = true;
                this.parameters = parameters;
                Activate();
                callSucceeded.Value = ExecutionSucceeded = Execute(Parameters.ToArray()); 
                Deactivate();
            }
        }

        public void Fork ( BooleanVariable forkSucceeded, List<Generic> parameters )
        {
            throw new Exception( "fix me" );

            Synchronous = false;
            Call( forkSucceeded, parameters );
            
            Engine.MHEGEngine.Instance.AsyncHandle( new AsynchStopped( this ) );
        }

        public void Stop ()
        {
            if ( RunningStatus )
                Deactivate();
        }
        #endregion


    }
}
